package com.vegetable.modules.service.finance.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vegetable.common.utils.R;
import com.vegetable.modules.entity.baseData.FundAccount;
import com.vegetable.modules.entity.finance.PaymentAccountRelease;
import com.vegetable.modules.entity.finance.PaymentLog;
import com.vegetable.modules.entity.finance.PaymentPurchase;
import com.vegetable.modules.entity.finance.Transactions;
import com.vegetable.modules.service.baseData.IFundAccountService;
import com.vegetable.modules.service.finance.IPaymentAccountReleaseService;
import com.vegetable.modules.service.finance.IPaymentLogService;
import com.vegetable.modules.service.finance.ITransactionsService;
import com.vegetable.modules.service.finance.UnionPayService;
import com.vegetable.modules.finance.service.ChinaUMSProxyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 银联支付服务实现类
 *
 * @author Qoder
 */
@Slf4j
@Service
public class UnionPayServiceImpl implements UnionPayService {

    @Autowired
    private ChinaUMSProxyService chinaUMSProxyService;

    @Autowired
    private IPaymentAccountReleaseService paymentAccountReleaseService;
    
    @Autowired
    private IFundAccountService fundAccountService;

    @Autowired
    private IPaymentLogService paymentLogService;
    
    @Autowired
    private ITransactionsService transactionsService;

    @Value("${unionpay.mchntNo:defaultMchntNo}")
    private String mchntNo;

    @Value("${unionpay.isProduction:false}")
    private boolean isProduction;

    @Override
    public R executeSinglePayment(PaymentPurchase payment) {
        try {
            // 从审批记录中获取收款人信息
            String payeeName = payment.getCustomerName();
            String payeeBankAccount = "";
            String payeeBankName = "";
            
            // 构建支付参数，使用获取到的收款人信息
            Map<String, String> params = buildPaymentParams(payment, payeeName, payeeBankAccount, payeeBankName);
            
            // 调用银联单笔支付接口
            Map<String, Object> result = chinaUMSProxyService.singlePayment(params, isProduction);
            
            if (result.containsKey("error")) {
                log.error("银联单笔支付接口调用失败: {}", result.get("error"));
                return R.fail("支付失败: " + result.get("error"));
            }
            
            // 记录支付日志
            PaymentLog paymentLog = recordPaymentLog(payment, params, result);
            
            // 如果支付成功，创建银行流水记录
            if (paymentLog.getStatus() == 1) {
                try {
                    createAndSaveBankTransaction(payment, params, result, paymentLog, payeeName, payeeBankAccount, payeeBankName);
                } catch (Exception e) {
                    log.error("创建银行流水记录时发生异常", e);
                }
            }
            
            return R.data(result, "支付成功");
        } catch (Exception e) {
            log.error("执行单笔支付时发生异常", e);
            return R.fail("支付异常: " + e.getMessage());
        }
    }
    
    @Override
    public R executeSinglePayment(PaymentPurchase payment, String payeeName, String payeeBankAccount, String payeeBankName) {
        try {
            // 构建支付参数，使用传入的收款人信息
            Map<String, String> params = buildPaymentParams(payment, payeeName, payeeBankAccount, payeeBankName);
            
            // 调用银联单笔支付接口
            Map<String, Object> result = chinaUMSProxyService.singlePayment(params, isProduction);
            
            if (result.containsKey("error")) {
                log.error("银联单笔支付接口调用失败: {}", result.get("error"));
                return R.fail("支付失败: " + result.get("error"));
            }
            
            // 记录支付日志
            PaymentLog paymentLog = recordPaymentLog(payment, params, result);
            
            // 如果支付成功，创建银行流水记录
            if (paymentLog.getStatus() == 1) {
                try {
                    createAndSaveBankTransaction(payment, params, result, paymentLog, payeeName, payeeBankAccount, payeeBankName);
                } catch (Exception e) {
                    log.error("创建银行流水记录时发生异常", e);
                }
            }
            
            return R.data(result, "支付成功");
        } catch (Exception e) {
            log.error("执行单笔支付时发生异常", e);
            return R.fail("支付异常: " + e.getMessage());
        }
    }

    @Override
    public R queryPaymentStatus(String sysOrderId, String mchntNo, String trxDate) {
        try {
            // 调用银联支付状态查询接口
            Map<String, Object> result = chinaUMSProxyService.queryPaymentStatus(sysOrderId, mchntNo, trxDate, isProduction);
            
            if (result.containsKey("error")) {
                log.error("银联支付状态查询接口调用失败: {}", result.get("error"));
                return R.fail("查询失败: " + result.get("error"));
            }
            
            return R.data(result, "查询成功");
        } catch (Exception e) {
            log.error("查询支付状态时发生异常", e);
            return R.fail("查询异常: " + e.getMessage());
        }
    }

    @Override
    public R queryPaymentBalance(String mchntNo) {
        try {
            // 调用银联可代付余额查询接口
            Map<String, Object> result = chinaUMSProxyService.queryPaymentBalance(mchntNo, isProduction);
            
            if (result.containsKey("error")) {
                log.error("银联可代付余额查询接口调用失败: {}", result.get("error"));
                return R.fail("查询失败: " + result.get("error"));
            }
            
            return R.data(result, "查询成功");
        } catch (Exception e) {
            log.error("查询可代付余额时发生异常", e);
            return R.fail("查询异常: " + e.getMessage());
        }
    }

    /**
     * 构建支付参数
     *
     * @param payment 付款信息
     * @return 支付参数
     */
    private Map<String, String> buildPaymentParams(PaymentPurchase payment) {
        Map<String, String> params = new HashMap<>();
        
        // 系统订单号
        params.put("sysOrderId", "PAY" + System.currentTimeMillis());
        
        // 商户编号
        params.put("mchntNo", mchntNo);
        
        // 回调地址
        params.put("responseUrl", "http://your-domain.com/payment/callback");
        
        // 获取付款账户信息
        QueryWrapper<PaymentAccountRelease> wrapper = new QueryWrapper<>();
        wrapper.eq("main_id", payment.getId());
        List<PaymentAccountRelease> accountReleases = paymentAccountReleaseService.getBaseMapper().selectList(wrapper);
        
        if (!accountReleases.isEmpty()) {
            PaymentAccountRelease accountRelease = accountReleases.get(0);
            // 收款人账户名
            params.put("revAcctName", accountRelease.getAccountName() != null ? accountRelease.getAccountName() : "");
            
            // 通过accountId关联到FundAccount获取账户信息
            if (accountRelease.getAccountId() != null) {
                FundAccount fundAccount = fundAccountService.getById(accountRelease.getAccountId());
                if (fundAccount != null) {
                    // 收款人账户号
                    if (fundAccount.getCardNo() != null) {
                        params.put("revAcctNo", fundAccount.getCardNo());
                    }
                    
                    // 收款人身份证号（如果有的话）
                    // 注意：FundAccount实体类中没有身份证号字段，这里暂时留空
                    // 如果需要身份证号，可能需要在其他地方获取或添加到FundAccount实体类中
                }
            }
            
            // 银行ID和银行编码暂时留空，因为PaymentAccountRelease和FundAccount中都没有这些字段
            // 如果业务需要，可能需要添加到实体类中或通过其他方式获取
        }
        
        // 支付金额（单位：分）
        if (payment.getMoney() != null) {
            BigDecimal payAmount = payment.getMoney().multiply(new BigDecimal(100));
            params.put("payAmt", payAmount.longValue() + "");
        } else {
            params.put("payAmt", "0");
        }
        
        // 备注
        params.put("remark", "付款单号: " + (payment.getDocNo() != null ? payment.getDocNo() : ""));
        
        // 交易时间
        params.put("timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        
        return params;
    }
    
    /**
     * 构建支付参数（使用传入的收款人信息）
     *
     * @param payment 付款信息
     * @param payeeName 收款人全称
     * @param payeeBankAccount 收款人银行账号
     * @param payeeBankName 收款人开户行
     * @return 支付参数
     */
    private Map<String, String> buildPaymentParams(PaymentPurchase payment, String payeeName, String payeeBankAccount, String payeeBankName) {
        Map<String, String> params = new HashMap<>();
        
        // 系统订单号
        params.put("sysOrderId", "PAY" + System.currentTimeMillis());
        
        // 商户编号
        params.put("mchntNo", mchntNo);
        
        // 回调地址
        params.put("responseUrl", "http://your-domain.com/payment/callback");
        
        // 收款人账户名（使用传入的参数）
        params.put("revAcctName", payeeName != null ? payeeName : "");
        
        // 收款人账户号（使用传入的参数）
        params.put("revAcctNo", payeeBankAccount != null ? payeeBankAccount : "");
        
        // 收款人开户行（使用传入的参数）
        params.put("bankName", payeeBankName != null ? payeeBankName : "");
        
        // 付款人信息（可以从系统配置或其他地方获取）
        // 这里暂时使用默认值，实际应用中应该从配置或数据库获取
        params.put("payerName", "默认付款人");
        params.put("payerAccount", "默认付款账号");
        params.put("payerBank", "默认付款银行");
        
        // 支付金额（单位：分）
        if (payment.getMoney() != null) {
            BigDecimal payAmount = payment.getMoney().multiply(new BigDecimal(100));
            params.put("payAmt", payAmount.longValue() + "");
        } else {
            params.put("payAmt", "0");
        }
        
        // 备注
        params.put("remark", "付款单号: " + (payment.getDocNo() != null ? payment.getDocNo() : ""));
        
        // 交易时间
        params.put("timestamp", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        
        return params;
    }

    /**
     * 记录支付日志
     *
     * @param payment 付款信息
     * @param params 支付参数
     * @param result 支付结果
     * @return 支付日志对象
     */
    private PaymentLog recordPaymentLog(PaymentPurchase payment, Map<String, String> params, Map<String, Object> result) {
        PaymentLog paymentLog = new PaymentLog();
        try {
            log.info("支付日志 - 付款ID: {}, 单据编号: {}, 支付金额: {}, 支付参数: {}, 支付结果: {}",
                    payment.getId(), payment.getDocNo(), payment.getMoney(), params, result);
            
            // 保存支付日志到数据库
            paymentLog.setPaymentId(payment.getId());
            paymentLog.setDocNo(payment.getDocNo());
            paymentLog.setAmount(payment.getMoney());
            paymentLog.setChannel(1); // 银联支付
            paymentLog.setPayParams(JSON.toJSONString(params));
            paymentLog.setPayResult(JSON.toJSONString(result));
            
            // 设置付款人信息
            paymentLog.setPayerName(params.get("payerName") != null ? params.get("payerName") : "");
            paymentLog.setPayerAccount(params.get("payerAccount") != null ? params.get("payerAccount") : "");
            paymentLog.setPayerBank(params.get("payerBank") != null ? params.get("payerBank") : "");
            
            // 设置收款人信息
            paymentLog.setPayeeName(params.get("revAcctName") != null ? params.get("revAcctName") : "");
            paymentLog.setPayeeAccount(params.get("revAcctNo") != null ? params.get("revAcctNo") : "");
            paymentLog.setPayeeBank(params.get("bankName") != null ? params.get("bankName") : "");
            
            // 根据支付结果设置状态
            if (result.containsKey("error")) {
                paymentLog.setStatus(2); // 支付失败
            } else {
                paymentLog.setStatus(1); // 支付成功
                paymentLog.setPayTime(new Date());
                
                // 如果返回结果中有交易流水号，保存到数据库
                if (result.containsKey("response")) {
                    String response = (String) result.get("response");
                    // 解析响应结果获取交易流水号
                    // 这里需要根据实际的银联回调格式来解析
                    paymentLog.setTransactionNo("TRAN" + System.currentTimeMillis());
                }
            }
            
            paymentLogService.save(paymentLog);
        } catch (Exception e) {
            log.error("记录支付日志时发生异常", e);
        }
        return paymentLog;
    }
    
    /**
     * 创建并保存银行流水记录
     *
     * @param payment 付款信息
     * @param params 支付参数
     * @param result 支付结果
     * @param paymentLog 支付日志
     */
    private void createAndSaveBankTransaction(PaymentPurchase payment, Map<String, String> params, Map<String, Object> result, PaymentLog paymentLog) {
        try {
            // 获取付款账户信息
            QueryWrapper<PaymentAccountRelease> wrapper = new QueryWrapper<>();
            wrapper.eq("main_id", payment.getId());
            List<PaymentAccountRelease> accountReleases = paymentAccountReleaseService.getBaseMapper().selectList(wrapper);
            
            if (!accountReleases.isEmpty()) {
                PaymentAccountRelease accountRelease = accountReleases.get(0);
                
                // 创建银行流水记录
                Transactions transaction = new Transactions();
                transaction.setTradingNo(paymentLog.getTransactionNo()); // 交易流水号
                transaction.setOrderNo(params.get("sysOrderId")); // 商户订单号
                transaction.setTradingTime(new Date()); // 交易时间
                transaction.setTradingAmount(payment.getMoney()); // 交易金额
                transaction.setTradingType("EXPENSE"); // 交易类型：支出
                transaction.setStatus("SUCCESS"); // 交易状态：成功
                transaction.setChannel("BANK"); // 支付渠道：银行
                transaction.setCounterparty(accountRelease.getAccountName()); // 交易对手方
                
                // 通过accountId关联到FundAccount获取账户信息
                if (accountRelease.getAccountId() != null) {
                    FundAccount fundAccount = fundAccountService.getById(accountRelease.getAccountId());
                    if (fundAccount != null) {
                        transaction.setFundAccountId(fundAccount.getId()); // 关联账户id
                        transaction.setFundAccountName(fundAccount.getAccountName()); // 关联账户名称
                        transaction.setBankNo(fundAccount.getCardNo()); // 银行卡号
                        // FundAccount类中没有getBankName方法，使用accountName作为银行名称
                        transaction.setBankName(fundAccount.getAccountName()); // 银行名称
                    }
                }

                transaction.setTradingDescription("付款单号: " + (payment.getDocNo() != null ? payment.getDocNo() : "")); // 交易描述
                
                // 保存到数据库
                List<Transactions> transactions = Arrays.asList(transaction);
                transactionsService.saveBatch1(transactions);
                
                log.info("银行流水记录创建成功，付款ID: {}, 单据编号: {}", payment.getId(), payment.getDocNo());
            }
        } catch (Exception e) {
            log.error("创建银行流水记录时发生异常", e);
        }
    }
    
    /**
     * 创建并保存银行流水记录（使用传入的收款人信息）
     *
     * @param payment 付款信息
     * @param params 支付参数
     * @param result 支付结果
     * @param paymentLog 支付日志
     * @param payeeName 收款人全称
     * @param payeeBankAccount 收款人银行账号
     * @param payeeBankName 收款人开户行
     */
    private void createAndSaveBankTransaction(PaymentPurchase payment, Map<String, String> params, Map<String, Object> result, PaymentLog paymentLog, String payeeName, String payeeBankAccount, String payeeBankName) {
        try {
            // 创建银行流水记录
            Transactions transaction = new Transactions();
            transaction.setTradingNo(paymentLog.getTransactionNo()); // 交易流水号
            transaction.setOrderNo(params.get("sysOrderId")); // 商户订单号
            transaction.setTradingTime(new Date()); // 交易时间
            transaction.setTradingAmount(payment.getMoney()); // 交易金额
            transaction.setTradingType("EXPENSE"); // 交易类型：支出
            transaction.setStatus("SUCCESS"); // 交易状态：成功
            transaction.setChannel("BANK"); // 支付渠道：银行
            transaction.setCounterparty(payeeName); // 交易对手方（使用传入的收款人全称）
            
            // 使用传入的收款人信息
            transaction.setFundAccountName(payeeName); // 关联账户名称
            transaction.setBankNo(payeeBankAccount); // 银行卡号
            transaction.setBankName(payeeBankName); // 银行名称

            transaction.setTradingDescription("付款单号: " + (payment.getDocNo() != null ? payment.getDocNo() : "")); // 交易描述
            
            // 保存到数据库
            List<Transactions> transactions = Arrays.asList(transaction);
            transactionsService.saveBatch1(transactions);
            
            log.info("银行流水记录创建成功，付款ID: {}, 单据编号: {}", payment.getId(), payment.getDocNo());
        } catch (Exception e) {
            log.error("创建银行流水记录时发生异常", e);
        }
    }

}